# HTML Wilderness.
from pdb import set_trace as debug

class Wild:
    BORDERING = False
    TILING = chr # list

    def __init__(self, (width, height), tile_base, sprite_base, default_tile,
                 default_start_location = None, **paint):

        self.tile_base = tile_base
        self.sprite_base = sprite_base
        self.tiles = []
        self.sprites = set()
        self.default_start_location = default_start_location or (0, 0)

        self.default_tile = (self + default_tile)

        self.array = [self.TILING(self.default_tile) * width] * height
        self.setTiles(paint)

    def setTiles(self, tiles):
        for ((x, y), tile) in tiles.iteritems():
            self[(x, y)] = tile

    def loadTiles(self, tiles):
        result = {}
        conversion = {}

        for (coord, tile) in tiles.iteritems():
            if tile in conversion:
                nr = conversion[tile]
            else:
                nr = conversion[tile] = (self + tile)

            result[coord] = nr

        return result

    # tileRows
    def rows(self):
        heightU = len(self.array) - 1
        for y in xrange(heightU + 1):
            def columns(row, y):
                widthU = len(row) - 1
                for x in xrange(widthU + 1):
                    borders = dict()

                    if self.BORDERING:
                        if x > 0:
                            borders['western'] = ord(row[x-1])
                        if x < widthU:
                            borders['eastern'] = ord(row[x+1])
                        if y > 0:
                            borders['northern'] = ord(self.array[y-1][x])
                        if y < heightU:
                            borders['southern'] = ord(self.array[y+1][x])

                    yield self.Tile(self, (x, y), ord(row[x]), borders)

            yield columns(self.array[y], y)

    class Tile:
        def __init__(self, wild, coords, code, borders = {}):
            self.wild = wild
            self.coords = coords
            self.code = code
            self.borders = borders

        def image(self):
            name = self.wild.tiles[self.code]

            # For the default tiling, just use its base.
            if self.code == self.wild.default_tile:
                return name

            # For all other tiles, add on the border names, in order.
            for b in ('northern', 'eastern', 'southern', 'western'):
                if b in self.borders:
                    # Determine overlapping factor.
                    name = '%s_%s' % (name, self.wild.tiles[self.borders[b]])

            return name

        def occupants(self):
            here = self.coords
            for sprite in self.wild.sprites:
                if sprite.location == here:
                    yield sprite

    def __setitem__(self, (x, y), tile):
        n = self.array[y]
        self.array[y] = '%s%s%s' % (n[:x], chr(tile), n[x+1:])

    def __add__(self, tile):
        self.tiles.append(tile)
        return len(self.tiles) - 1

    class Sprite:
        def __init__(self, wild, image = None, location = None, selected = False):
            self.wild = wild
            self.image = image
            self.selected = selected

            self.visible = True

            if location is None:
                location = wild.default_start_location

            self.location = location

        def image(self):
            return self.image

    def put_sprite(self, *args, **kwd):
        sprite = self.Sprite(self, *args, **kwd)
        self.sprites.add(sprite)
        return sprite

def loadRegion(filename):
    import yaml
    config = yaml.load(open(filename))

    (width, height) = eval(config['size'])
    tile_base       = config['tile-base']
    sprite_base     = config['sprite-base']
    default         = config['default']

    tiles           = config.get('tiles', [])
    sprites         = config.get('sprites', [])

    region = Wild((width, height), tile_base, sprite_base, default)

    # Set coordinate terrain.
    unit = dict()
    for coords in tiles:
        for (xy, name) in coords.iteritems():
            unit[eval(xy)] = name

    tiles = region.loadTiles(unit)
    region.setTiles(tiles)

    # Load sprites.
    for sp in sprites:
        if 'location' in sp:
            sp['location'] = eval(sp['location'])

        region.put_sprite(**sp)

    return region

def main(argv = None):
    from optparse import OptionParser
    parser = OptionParser()
    parser.add_option('-d', '--debug', action = 'store_true')
    (options, args) = parser.parse_args(argv)

    if options.debug:
        debug()

    for filename in args:
        # Load django templates.
        loadRegion(filename)

if __name__ == '__main__':
    main()
